home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C ++ / Frameworks / MacZoop 1.6.5 / More Classes / Progress Dialog / ZProgress.cpp next >
Encoding:
C/C++ Source or Header  |  1997-07-15  |  11.2 KB  |  437 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************************
  2. *
  3. *
  4. *            ObjectMacZapp        -- a standard Mac OOP application template
  5. *
  6. *
  7. *
  8. *            ZProgress.cpp        -- a progress dialog
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *            © 1996, Graham Cox
  15. *
  16. *
  17. *
  18. *
  19. *************************************************************************************************/
  20.  
  21. #include    "ZProgress.h"
  22. #include    "MacZoop.h"
  23.  
  24. extern ZCommander*        gCurHandler;
  25.  
  26. /*-----------------------------***  CONSTRUCTOR  ***------------------------------------*/
  27.  
  28. // this is an alternative constructor to set the striped/proportional mode explicitly, or
  29. // you can use the other constructor passing a negative value to default to striped mode.
  30.  
  31.  
  32. ZProgress::ZProgress(     ZCommander* aBoss,
  33.                           const short dialogID,
  34.                            const long maxValue,
  35.                            const short pType,
  36.                            const ProgType aMode )
  37.     : ZDialog( aBoss, dialogID )
  38. {
  39.     theType = pType;
  40.     
  41.     // max should not be less than 1 to avoid potential divide by zero error
  42.     
  43.     max = MAX( 1, ( maxValue & 0x7FFFFFFF ));
  44.     
  45.     // if maxValue is negative, default to indeterminate progress. Otherwise use whatever
  46.     // was passed along in the <aMode> parameter.
  47.     
  48.     if ( maxValue & 0x80000000 )
  49.         displayMode = kIndeterminateProgress;
  50.     else
  51.         displayMode = aMode;
  52.     
  53.     value = 0;
  54.     deferTime = 0;
  55.     createTime = TickCount();
  56.     fAbort = FALSE;
  57.     SetRect( &pRect, 0, 0, 0, 0 );
  58.  
  59.     stripesPat = GetPixPat( kStdStripedPattern );
  60.     
  61.     InitZWindow();
  62. }            
  63.  
  64.  
  65. /*------------------------------***  DESTRUCTOR  ***------------------------------------*/
  66.  
  67. ZProgress::~ZProgress()
  68. {
  69.     Hide();
  70.     
  71.     // remove the stripes pattern if present
  72.     
  73.     if ( stripesPat )
  74.         DisposePixPat( stripesPat );
  75.     
  76.     // this type of dialog is not usually closed from outside, but is simply
  77.     // destroyed. In this case we need to make sure the chain of command is
  78.     // maintained correctly. We can't call Close since that deletes the object
  79.     // creating an infinite loop. Thus we simply manipulate the handler directly.
  80.     
  81.     if ( gCurHandler == this )                        // make the current handler this
  82.         gCurHandler = itsBoss;                        // one's boss- i.e. the application
  83. }
  84.  
  85. /*---------------------------------***  SETUP  ***--------------------------------------*/
  86. /*    
  87.  
  88. overrides ZDialog to set up the button and bar according to the type
  89. ----------------------------------------------------------------------------------------*/
  90.  
  91. void        ZProgress::SetUp()
  92. {
  93.     // set up the text of the button to the requested type of dialog
  94.     
  95.     short    iType;
  96.     Handle    iHand;
  97.     Rect    iBox;
  98.  
  99.     if ( theType == kNoButton )
  100.     {
  101.         HideDialogItem( macWindow, kCancelButton );
  102.         
  103.         // extend the length of the bar in this case so that it is properly
  104.         // centred in the dialog window. (Looks better).
  105.         
  106.         GetDialogItem( macWindow, kBarItem, &iType, &iHand, &iBox );
  107.         
  108.         iBox.right = macWindow->portRect.right - iBox.left;
  109.         SetDialogItem( macWindow, kBarItem, iType, iHand, &iBox );
  110.     }
  111.     else
  112.     {
  113.         // the button is visible, but maybe its text is different.
  114.         // By default it is Cancel, but may need to say "Stop"
  115.         
  116.         if ( theType == kStopType )
  117.         {
  118.             Str31    stopStr;
  119.             
  120.             GetDialogItem(macWindow, kCancelButton, &iType, &iHand, &iBox);
  121.             
  122.             // sanity check- this IS a control, isn't it?
  123.             
  124.             if ( iType & ctrlItem )
  125.             {
  126.                 GetIndString( stopStr, 128, kStopStringID );
  127.                 SetControlTitle(( ControlHandle ) iHand, stopStr );
  128.             }
  129.         }
  130.     }
  131.     
  132.     // call inherited SetUp in case base class wants to do something
  133.  
  134.     inherited::SetUp();
  135. }
  136.  
  137. /*---------------------------------***  DRAW  ***---------------------------------------*/
  138. /*    
  139. refresh the dialog
  140. ----------------------------------------------------------------------------------------*/
  141.  
  142. void        ZProgress::Draw()
  143. {
  144.     SetRect( &pRect, 0, 0, 0, 0 );
  145.     inherited::Draw();
  146. }
  147.  
  148.  
  149. /*-----------------------------***  DRAWUSERITEM  ***-----------------------------------*/
  150. /*    
  151.  
  152. Draws the progress bar user item
  153. ----------------------------------------------------------------------------------------*/
  154.  
  155. void        ZProgress::DrawUserItem( const short item )
  156. {
  157.     // override to draw the progress bar user-item. This is also called directly when
  158.     // InformProgress is called to update the bar.
  159.     
  160.     if ( item == kBarItem )
  161.     {
  162.         short            iType, barLength;
  163.         Handle            iHand;
  164.         Rect            iBox, barBox;
  165.         PixPatHandle    backPP, forePP;
  166.         
  167.         GetDialogItem( macWindow, item, &iType, &iHand, &iBox );
  168.         FrameRect( &iBox );
  169.                         
  170.         #ifdef _GREYSCALE_APPEARANCE
  171.  
  172.         FrameGrayRect( &iBox );
  173.         
  174.         #endif
  175.         InsetRect( &iBox, 1, 1 );
  176.         
  177.         // if this is a striped bar, all we do is cycle the stripe and
  178.         // repaint it.
  179.         
  180.         if ( displayMode == kIndeterminateProgress )
  181.         {
  182.             if ( stripesPat )
  183.             {
  184.                 CycleStripe();
  185.                 FillCRect( &iBox, stripesPat );
  186.             }
  187.             else
  188.                 InvertRect( &iBox );    // not a great deal we can do if no resources...
  189.         }
  190.         else
  191.         {
  192.             // compute the size of the barBox, based on max and value
  193.             
  194.             barLength = (short)(((double) value / (double) max) * (long)( iBox.right - iBox.left ));            
  195.             barBox = iBox;
  196.             barBox.right = MIN( barBox.left + barLength, iBox.right );
  197.             
  198.             // if this is different to the previously calculated bar, repaint it
  199.             
  200.             if (! EqualRect( &pRect, &barBox ))
  201.             {
  202.                 try
  203.                 {
  204.                     // if this is the first update, pRect will be empty, so
  205.                     // simply fill in the background
  206.                     
  207.                     if ( EmptyRect( &pRect ))
  208.                     {
  209.                         FailNIL( backPP = GetPixPat( kStdBackPattern ));
  210.                         FillCRect( &iBox, backPP );
  211.                         DisposePixPat( backPP );
  212.                     }
  213.                     
  214.                     FailNIL( forePP = GetPixPat( kStdBarPattern ));
  215.                     FillCRect( &barBox, forePP );
  216.                     DisposePixPat( forePP );
  217.                 }
  218.                 catch ( OSErr err )
  219.                 {
  220.                     // if the patterns don't exist, paint the bar instead.
  221.                     
  222.                     PaintRect( &barBox );
  223.                     
  224.                     // do not propagate exceptions from here
  225.                 }
  226.                 
  227.                 // update pRect if the window is visible.
  228.                 
  229.                 if ( IsVisible())
  230.                     pRect = barBox;
  231.             }
  232.         }
  233.     }
  234.     else
  235.         inherited::DrawUserItem( item );
  236. }
  237.  
  238.  
  239. /*-------------------------------***  CLICKITEM  ***------------------------------------*/
  240. /*    
  241. set the abort flag if the user clicked cancel or stop
  242. ----------------------------------------------------------------------------------------*/
  243.  
  244. void        ZProgress::ClickItem( const short theItem )
  245. {
  246.     fAbort = ( theItem == kCancelButton );
  247. }
  248.  
  249.  
  250. /*-----------------------------***  INFORMPROGRESS  ***---------------------------------*/
  251. /*    
  252. called to keep the progress dialog moving as a lengthy operation proceeds
  253. ----------------------------------------------------------------------------------------*/
  254.  
  255. Boolean        ZProgress::InformProgress( const long progressSoFar )
  256. {
  257.     CGrafPtr    savePort;
  258.     GDHandle    saveDevice;
  259.     
  260.     // save the current port and device in case we were called from
  261.     // some function that had changed it. Note that the caller should be
  262.     // aware that the port, device, etc MAY not be exactly preserved
  263.     // across calls to this, since this processes events, etc.
  264.     
  265.     GetGWorld( &savePort, &saveDevice );
  266.     SetGDevice( GetMainDevice());
  267.     
  268.     // update the value we have got to here
  269.     
  270.     value = progressSoFar;
  271.     
  272.     // if it is time to show the progress dialog, make it visible
  273.     
  274.     if (( TickCount() > ( createTime + deferTime )) && !IsVisible())
  275.         Select();
  276.         
  277.     // let the application handle any pending event, so we get updated, etc. etc
  278.     // any exceptions arising are handled by the caller. Note that in the
  279.     // event of an exception, the device is set to the main device, which
  280.     // is possibly safer, though if the caller knows different, it should
  281.     // try to do the right thing.
  282.     
  283.     gApplication->Process1Event();
  284.     
  285.     // redraw the progress bar
  286.     
  287.     Focus();
  288.     DrawUserItem( kBarItem );
  289.     
  290.     // restore what we think is the port and device
  291.     
  292.     SetGWorld( savePort, saveDevice );
  293.  
  294.     return !fAbort;    // carry on until this flag is set
  295. }
  296.  
  297.  
  298. /*--------------------------------***  SETDELAY  ***------------------------------------*/
  299. /*    
  300. set the initial deferment delay
  301. ----------------------------------------------------------------------------------------*/
  302.  
  303. void        ZProgress::SetDelay( const short delayTicks )
  304. {
  305.     deferTime = delayTicks;
  306. }
  307.  
  308.  
  309. /*-------------------------------***  SETMESSAGE  ***-----------------------------------*/
  310. /*    
  311. set the message string to the string passed
  312. ----------------------------------------------------------------------------------------*/
  313.  
  314. void        ZProgress::SetMessage( const Str255& aMsg )
  315. {
  316.     SetValue( kMessageItem, aMsg );
  317. }
  318.  
  319.  
  320. /*-------------------------------***  SETMESSAGE  ***-----------------------------------*/
  321. /*    
  322. set the message to the STR# resource with ID and index passed
  323. ----------------------------------------------------------------------------------------*/
  324.  
  325. void        ZProgress::SetMessage( const short resID, const short index )
  326. {
  327.     Str255    aStr;
  328.     
  329.     GetIndString( aStr, resID, index );
  330.     SetMessage( aStr );
  331. }
  332.  
  333.  
  334. /*---------------------------------***  SETMODE  ***------------------------------------*/
  335. /*    
  336. switch from stripey to proportional and back
  337. ----------------------------------------------------------------------------------------*/
  338.  
  339. void        ZProgress::SetMode( ProgType aMode )                        
  340. {
  341.     if ( aMode != displayMode )
  342.     {
  343.         displayMode = aMode;
  344.     
  345.         // force a re-draw of the whole bar
  346.         
  347.         Draw();
  348.     }
  349. }
  350.  
  351.  
  352. /*----------------------------------***  FILTER  ***------------------------------------*/
  353. /*    
  354. maps command-period to the cancel/stop button, unless a kNoButton type
  355. ----------------------------------------------------------------------------------------*/
  356.  
  357. Boolean        ZProgress::Filter( EventRecord* theEvent )
  358. {
  359.     Boolean fullyHandled = FALSE;
  360.  
  361.     if ( theType != kNoButton )
  362.     {
  363.         if ( theEvent->what == keyDown )
  364.         {
  365.             char theKey = theEvent->message & charCodeMask;
  366.             
  367.             if ((theKey == '.') &&
  368.                 ((theEvent->modifiers & cmdKey) == cmdKey))
  369.             {
  370.                 FakeClick( kCancelButton );
  371.                 
  372.                 fullyHandled = TRUE;
  373.             }
  374.         }
  375.     }
  376.     
  377.     return fullyHandled;
  378. }
  379.  
  380.  
  381. /*-------------------------------***  CYCLESTRIPE  ***----------------------------------*/
  382. /*    
  383. for stripe bar, this moves the pattern by <loop>, animating it. This is designed to be called
  384. repeatedly, and only changes the pattern every few (3, in this case) ticks.
  385. ----------------------------------------------------------------------------------------*/
  386.  
  387. void        ZProgress::CycleStripe()
  388. {
  389.     if ( stripesPat && IsVisible())
  390.     {
  391.         // see if it is time yet. Notethat this function re-uses the timing
  392.         // data members, but since they are only used before the dialog is visible,
  393.         // this is OK in this particular case.
  394.         
  395.         deferTime = TickCount();
  396.         
  397.         if ( deferTime > ( createTime + 3 ))
  398.         {
  399.             createTime = deferTime;
  400.     
  401.             // modify the pattern. We do this by copying the
  402.             // image data of the pattern to itself in another
  403.             // position, based on the pixmap dimensions.
  404.             
  405.             long    patImgSize;
  406.             short    rowBytes, loop = 2;
  407.             Ptr        tempBuffer;
  408.             
  409.             rowBytes = (*(*stripesPat)->patMap)->rowBytes & 0x3FFF;
  410.             patImgSize = GetHandleSize((*stripesPat)->patData );
  411.             
  412.             // copy the top row of the data into a temporary buffer
  413.             // that we create. This holds one row of image data.
  414.             
  415.             tempBuffer = NewPtr( rowBytes );
  416.             
  417.             do
  418.             {
  419.                 BlockMoveData(*(*stripesPat)->patData, tempBuffer, rowBytes);
  420.                 
  421.                 // copy the rest of the data up one row
  422.                 
  423.                 BlockMoveData((*(*stripesPat)->patData) + rowBytes, *(*stripesPat)->patData, patImgSize - rowBytes);
  424.             
  425.                 // copy the temp row to the bottom of the image
  426.                 
  427.                 BlockMoveData(tempBuffer, (*(*stripesPat)->patData) + patImgSize - rowBytes, rowBytes);
  428.             }
  429.             while (--loop);
  430.             
  431.             DisposePtr( tempBuffer );
  432.             PixPatChanged( stripesPat );
  433.         }
  434.     }
  435. }
  436.  
  437.